package com.yc.utilslib.reader.protocol.tagvalue;

import com.yc.utilslib.utils.ByteUtils;
import com.yc.utilslib.utils.DateUtils;
import com.yc.utilslib.utils.StringUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;

/**
 * 作者：TanTun
 * 时间：2017/10/18
 * 邮箱：32965926@qq.com
 * 描述：TAG枚举定义
 */

public enum Tag {
    SYS_MACHINE_NO("机号", (short)0x1001, (short)2),             //机号
    SYS_TIME("系统时间", (short)0x1008, (short)7),               //年、月、日、时、分、秒
    SYS_CMD_RET("命令执行结果", (short)0x1013, (short)1),           //0-成功，1-失败
    SYS_WORK_MODE("工作模式", (short)0x1025, (short)1),            //0-主动模式，1-被动模式
    SYS_COMM_MODE("通讯模式", (short)0x1026, (short)1),            //0-串口通讯，1-USB通讯
    SYS_READ_MODE("读卡内容", (short)0x1027, (short)1),            //0-只读物理ID，1-卡片物理ID和指定扇区内容
    SYS_PARA_XF_SECTOR("卡片消费扇区", (short)0x4002, (short)1),	//卡片消费扇区
    SYS_PARA_SK_SECTOR("卡片水控扇区", (short)0x4009, (short)1),	//卡片水控扇区
    SYS_PARA_KEY_A("A密钥", (short)0x4003, (short)6),            //卡片访问初始A密钥
    SYS_PARA_KEY_B("B密钥", (short)0x400A, (short)6),            //卡片访问初始B密钥
    CARD_PARA_TYPE("用户卡类", (short)0x1015, (short)1),          //卡类1~32类卡
    CARD_PARA_FLAG("卡片标识", (short)0x4007, (short)1),          //卡片标识
    CARD_PARA_AUTH_TYPE("认证类型", (short)0x4008, (short)1),	    //0x60-A密钥认证，0x61-密钥认证
    CARD_PARA_BLOCK_ADDRESS("卡片块地址", (short)0x4006, (short)1),//卡片块地址
    CARD_PARA_ID("物理ID", (short)0x6001, (short)4),				 //物理ID
    CARD_PARA_SERIAL_NO("发卡序列号", (short)0x6008, (short)4),   //发卡序列号
    CARD_PARA_EXCESS_KEY("超额密钥", (short)0x6011, (short)2),   //用户卡超额密钥
    CARD_PARA_STOP_DATE("卡有效期", (short)0x6012, (short)3),		//用户卡使用有效期
    CARD_PARA_REST_MONEY("用户卡余额", (short)0x6009, (short)4),	//用户卡余额
    CARD_PARA_USED_MONEY("消费金额", (short)0x600C, (short)4),	//用户卡消费额
    CARD_PARA_CONSUME_TIME("消费时间", (short)0x6003, (short)6),	//消费时间
    CARD_PARA_TOTAL_USED_TIMES("消费总次数", (short)0x600D, (short)2),//卡片消费次数
    CARD_PARA_TOTAL_USED_MONEY("消费总金额", (short)0x6019, (short)2),//卡片消费累积金额
    CARD_BLOCK_DATA("块数据", (short)0x601A, (short)16),         //块数据
    CARD_SECTOR_DATA("块数据", (short)0x601B, (short)48),        //扇区数据
    CARD_FACTORY_FLAG("卡片厂家标记", (short)0x601C, (short)2),   //卡片厂家标记
    CARD_PARA_NAME("卡片姓名数据", (short)0x6030, (short)48);   //卡片姓名数据

    private String name;
    private short value;
    private short len;

    Tag(String name, short value, short len) {
        this.name = name;
        this.value = value;
        this.len = len;
    }

    public static String getName(short value) {
        for (Tag c : Tag.values()) {
            if (c.getValue() == value) {
                return c.name;
            }
        }
        return null;
    }

    public static Tag getTag(short value) {
        for (Tag c : Tag.values()) {
            if (c.getValue() == value) {
                return c;
            }
        }
        return null;
    }

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public short getValue() {
        return value;
    }
    public void setValue(short index) {
        this.value = index;
    }
    public short getLength() {
        return len;
    }

    public Object byteArrayToValue(byte[] data) {
        switch (this) {
            case SYS_MACHINE_NO: return TagFunction.toUnsignedShort(data);
            case SYS_TIME: return TagFunction.toLongDateTime(data);
            case SYS_CMD_RET: return TagFunction.toByte(data);
            case SYS_WORK_MODE: return TagFunction.toByte(data);
            case SYS_COMM_MODE: return TagFunction.toByte(data);
            case SYS_READ_MODE: return TagFunction.toByte(data);
            case SYS_PARA_XF_SECTOR: return TagFunction.toByte(data);
            case SYS_PARA_SK_SECTOR: return TagFunction.toByte(data);
            case SYS_PARA_KEY_A: return TagFunction.toBytes(len, data);
            case SYS_PARA_KEY_B: return TagFunction.toBytes(len, data);
            case CARD_PARA_TYPE: return TagFunction.toByte(data);
            case CARD_PARA_FLAG: return TagFunction.toByte(data);
            case CARD_PARA_AUTH_TYPE: return TagFunction.toByte(data);
            case CARD_PARA_BLOCK_ADDRESS: return TagFunction.toByte(data);
            case CARD_PARA_ID: return TagFunction.toUnsignedInt(data);
            case CARD_PARA_SERIAL_NO: return TagFunction.toUnsignedInt(data);
            case CARD_PARA_EXCESS_KEY: return TagFunction.toBCD(data);
            case CARD_PARA_STOP_DATE: return TagFunction.toShortDateTime(data);
            case CARD_PARA_REST_MONEY: return TagFunction.toBigDecimal(data);
            case CARD_PARA_USED_MONEY: return TagFunction.toBigDecimal(data);
            case CARD_PARA_CONSUME_TIME: return TagFunction.toLongDateTime(data);
            case CARD_PARA_TOTAL_USED_TIMES: return TagFunction.toUnsignedShort(data);
            case CARD_PARA_TOTAL_USED_MONEY: return TagFunction.toBigDecimal(data);
            case CARD_BLOCK_DATA: return TagFunction.toBytes(len, data);
            case CARD_SECTOR_DATA: return TagFunction.toBytes(len, data);
            case CARD_FACTORY_FLAG: return TagFunction.toUnsignedShort(data);
            case CARD_PARA_NAME: return TagFunction.toBytes(len, data);
        }

        return null;
    }
    public byte[] stringToValue(String data) {
        switch (this) {
            case SYS_MACHINE_NO: return TagFunction.fromUnsignedShort(Integer.valueOf(data));
            case SYS_TIME:
                try {
                    return TagFunction.fromLongDateTime(DateUtils.YYYYMMDDHHMMSS_LONG.parse(data));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            case SYS_CMD_RET: return TagFunction.fromByte(Byte.valueOf(data));
            case SYS_WORK_MODE: return TagFunction.fromByte(Byte.valueOf(data));
            case SYS_COMM_MODE: return TagFunction.fromByte(Byte.valueOf(data));
            case SYS_READ_MODE: return TagFunction.fromByte(Byte.valueOf(data));
            case SYS_PARA_XF_SECTOR: return TagFunction.fromByte(Byte.valueOf(data));
            case SYS_PARA_SK_SECTOR: return TagFunction.fromByte(Byte.valueOf(data));
            case SYS_PARA_KEY_A: return TagFunction.fromHexString(data);
            case SYS_PARA_KEY_B: return TagFunction.fromHexString(data);
            case CARD_PARA_TYPE: return TagFunction.fromByte(Byte.valueOf(data));
            case CARD_PARA_FLAG: return TagFunction.fromByte(Byte.valueOf(data));
            case CARD_PARA_AUTH_TYPE: return TagFunction.fromByte(Byte.valueOf(data));
            case CARD_PARA_BLOCK_ADDRESS: return TagFunction.fromByte(Byte.valueOf(data));
            case CARD_PARA_ID: return TagFunction.fromUnsignedInt(Long.valueOf(data));
            case CARD_PARA_SERIAL_NO: return TagFunction.fromUnsignedInt(Long.valueOf(data));
            case CARD_PARA_EXCESS_KEY: return TagFunction.fromBCD(data);
            case CARD_PARA_STOP_DATE:
                try {
                    return TagFunction.fromLongDateTime(DateUtils.YYYYMMDD_LONG.parse(data));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            case CARD_PARA_REST_MONEY: return TagFunction.fromBigDecimal(new BigDecimal(data));
            case CARD_PARA_USED_MONEY: return TagFunction.fromBigDecimal(new BigDecimal(data));
            case CARD_PARA_CONSUME_TIME: try {
                return TagFunction.fromLongDateTime(DateUtils.YYYYMMDDHHMMSS_LONG.parse(data));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            case CARD_PARA_TOTAL_USED_TIMES: return TagFunction.fromUnsignedShort(Integer.valueOf(data));
            case CARD_PARA_TOTAL_USED_MONEY: return TagFunction.fromBigDecimal(new BigDecimal(data));
            case CARD_BLOCK_DATA: return TagFunction.fromHexString(data);
            case CARD_SECTOR_DATA: return TagFunction.fromHexString(data);
            case CARD_FACTORY_FLAG: return TagFunction.fromUnsignedShort(Integer.valueOf(data));
            case CARD_PARA_NAME: return TagFunction.fromHexString(data);
        }

        return null;
    }
    public byte[] valueToByteArray(Object value) {
        switch (this) {
            case SYS_MACHINE_NO: return TagFunction.fromUnsignedShort((Integer)value);
            case SYS_TIME: return TagFunction.fromLongDateTime((Date)value);
            case SYS_CMD_RET: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case SYS_WORK_MODE: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case SYS_COMM_MODE: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case SYS_READ_MODE: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case SYS_PARA_XF_SECTOR: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case SYS_PARA_SK_SECTOR: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case SYS_PARA_KEY_A: return TagFunction.fromBytes((byte[])value);
            case SYS_PARA_KEY_B: return TagFunction.fromBytes((byte[])value);
            case CARD_PARA_TYPE: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case CARD_PARA_FLAG: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case CARD_PARA_AUTH_TYPE: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case CARD_PARA_BLOCK_ADDRESS: return TagFunction.fromByte((byte)((Integer)value & 0xFF));
            case CARD_PARA_ID: return TagFunction.fromUnsignedInt((Long)value);
            case CARD_PARA_SERIAL_NO: return TagFunction.fromUnsignedInt((Long)value);
            case CARD_PARA_EXCESS_KEY: return TagFunction.fromBCD((String)value);
            case CARD_PARA_STOP_DATE: return TagFunction.fromShortDateTime((Date)value);
            case CARD_PARA_REST_MONEY: return TagFunction.fromBigDecimal((BigDecimal)value);
            case CARD_PARA_USED_MONEY: return TagFunction.fromBigDecimal((BigDecimal)value);
            case CARD_PARA_CONSUME_TIME: return TagFunction.fromLongDateTime((Date)value);
            case CARD_PARA_TOTAL_USED_TIMES: return TagFunction.fromUnsignedShort((Integer)value);
            case CARD_PARA_TOTAL_USED_MONEY: return TagFunction.fromBigDecimal((BigDecimal)value);
            case CARD_BLOCK_DATA: return TagFunction.fromBytes((byte[])value);
            case CARD_SECTOR_DATA: return TagFunction.fromBytes((byte[])value);
            case CARD_FACTORY_FLAG: return TagFunction.fromUnsignedShort((Integer)value);
            case CARD_PARA_NAME: return TagFunction.fromBytes((byte[])value);
        }

        return null;
    }
    public String format(Object value) {
        switch (this) {
            case SYS_MACHINE_NO: return Integer.toString((Integer)value);
            case SYS_TIME: return DateUtils.YYYYMMDDHHMMSS_LONG.format((Date)value);
            case SYS_CMD_RET: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case SYS_WORK_MODE: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case SYS_COMM_MODE: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case SYS_READ_MODE: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case SYS_PARA_XF_SECTOR: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case SYS_PARA_SK_SECTOR: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case SYS_PARA_KEY_A: return ByteUtils.byteArrayToHexString((byte[])value);
            case SYS_PARA_KEY_B: return ByteUtils.byteArrayToHexString((byte[])value);
            case CARD_PARA_TYPE: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case CARD_PARA_FLAG: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case CARD_PARA_AUTH_TYPE: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case CARD_PARA_BLOCK_ADDRESS: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value & 0xFF)));
            case CARD_PARA_ID: return Long.toString((long)value);
            case CARD_PARA_SERIAL_NO: return Long.toString((long)value);
            case CARD_PARA_EXCESS_KEY: return (String)value;
            case CARD_PARA_STOP_DATE: return DateUtils.YYYYMMDD_LONG.format((Date)value);
            case CARD_PARA_REST_MONEY: return ((BigDecimal)value).setScale(2, BigDecimal.ROUND_DOWN).toString();
            case CARD_PARA_USED_MONEY: return ((BigDecimal)value).setScale(2, BigDecimal.ROUND_DOWN).toString();
            case CARD_PARA_CONSUME_TIME: return DateUtils.YYYYMMDDHHMMSS_LONG.format((Date)value);
            case CARD_PARA_TOTAL_USED_TIMES: return Integer.toString(ByteUtils.byteToUnsignedByte((byte)((Integer)value >> 24 & 0xFF)));
            case CARD_PARA_TOTAL_USED_MONEY: return ((BigDecimal)value).setScale(2, BigDecimal.ROUND_DOWN).toString();
            case CARD_BLOCK_DATA: return ByteUtils.byteArrayToHexString((byte[])value);
            case CARD_SECTOR_DATA: return ByteUtils.byteArrayToHexString((byte[])value);
            case CARD_FACTORY_FLAG: return Short.toString((short)value);
            case CARD_PARA_NAME: return ByteUtils.byteArrayToHexString((byte[])value);
        }

        return StringUtils.EMPTY;
    }
}
